/*
    kOTF Open Trace Format - a library for generating execution traces.
    Copyright 2012 Daniel K. O.

    kOTF is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    kOTF is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with kOTF.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef KOTF_SESSION_IMPL_H
#define KOTF_SESSION_IMPL_H

#include <kotf/Records.hpp>
#include <kotf/Session.hpp>

#include "TypesInternal.hpp"
#include "Writer.hpp"

namespace kotf {

    class Stream;
    class Writer;

    class SessionImpl {

        typedef unordered_map<string, Stream*> StreamMap;

        typedef unordered_map<uint64_t, State> StateIdMap;
        typedef unordered_map<string, State>   StateStrMap;
    
        typedef unordered_map<uint64_t, Counter> CounterIdMap;
        typedef unordered_map<string, Counter>   CounterStrMap;

        typedef unordered_map<uint64_t, Channel> ChannelIdMap;
        typedef unordered_map<string, Channel>   ChannelStrMap;



        Session *iface;

        const string name;

        StreamMap streams;
        uint64_t nextStreamId;
        mutex streamsMutex;


        StateIdMap stateById;
        StateStrMap stateByName;
        uint64_t nextStateId;
        mutex statesMutex;

        CounterIdMap counterById;
        CounterStrMap counterByName;
        uint64_t nextCounterId;
        mutex countersMutex;

        ChannelIdMap channelById;
        ChannelStrMap channelByName;
        uint64_t nextChannelId;
        mutex channelsMutex;

        const uint64_t startTime;

        bool enabled;

        Writer writer;


    private:
        void flushStreams();
        void dumpDefinitions();

    public:

        SessionImpl(Session* s, const string& sname);
        ~SessionImpl();

        const string& getName() const;

        Session& getSession();

        void enable(); ///< Enable trace generation (default)

        /** \brief Disable trace generation.
            This function will block until the writer thread exits. Data traced so far may be lost,
            so this should be called right after construction of the session.
         */
        void disable();
        bool isEnabled() const; ///< wheter the session is enabled
        
        Stream& getStream(const string& s); ///< returns or constructs a new Stream with this name

        State getState(uint64_t st) throw (InvalidStateId); ///< returns an existing State or throws InvalidStateId
        State getState(const string& st); ///< returns or creates a new State

        Counter getCounter(uint64_t cnt) throw (InvalidCounterId); ///< returns an existing Counter or throws InvalidCounterId
        Counter getCounter(const string& cnt); ///< returns or creates a new Counter

        Channel getChannel(uint64_t ch) throw (InvalidChannelId); ///< returns an existing Channel or throws InvalidChannelId
        Channel getChannel(const string& ch); ///< returns or creates a new Channel


        uint64_t getTime() const; ///< returns the nanoseconds since the start of the session


        EventBuffer* getEventBuffer(StreamImpl* stream);
        void submit(EventBuffer* eb);


        static const char * magic;

    };

}

#endif
